home *** CD-ROM | disk | FTP | other *** search
- ;* STREAM.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* C stuff recoded in assembly language (phtew!) *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
-
- CODESEG
- ;************************************************************************
- ;* Convert flonum to bignum *
- ;* Calling sequence: flotobig(flo,bigbuf) *
- ;* Where flo: double-length flonum such that abs(flo)>=1 *
- ;* bigbuf: pointer to buffer for bignum formation *
- ;************************************************************************
- PROC C flotobig USES si di, @@flo:QWORD, @@bignum:WORD
- LOCAL @@status:WORD, @@tempbig:QWORD
- push ds ; Assume es = ds
- pop es
- fld [@@flo]
- ftst
- mov di, [@@bignum]
- fstsw [@@status]
- mov [(BIGDATA di).sign], 0
- mov ax, [@@status]
- fabs
- sahf
- jnz @@notzero ; handle special case
- @@zero:
- mov [(BIGDATA di).len], 1
- mov [(BIGDATA di).lsw], 0
- jmp @@done
-
- @@notzero:
- jnc @@positive
- inc [(BIGDATA di).sign]
- @@positive:
- fxtract
- fxch st(1)
- fistp [@@status] ; get the exponent
- cmp [@@status], 64
- jg @@bigenough
- fstp st(0) ; drop the mantissa
- fld [@@flo]
- lea si, [@@tempbig+(TYPE QWORD)]
- fabs
- mov cx, 4 ; 4 words maximum
- fistp [@@tempbig]
- @@truncateloop:
- dec si
- dec si
- cmp [WORD si], 0
- loopz @@truncateloop
- @@mswfound:
- jz @@zero
- lea si, [@@tempbig]
- inc cx
- mov [(BIGDATA di).len], cx
- lea di, [(BIGDATA di).lsw]
- rep movsw
- jmp @@done
-
- @@bigenough:
- mov bx, [@@status] ; get the exponent
- lea ax, [bx-1]
- and ax, 0fh ; keep roundoff
- inc ax
- add ax, 30h ; ax is in range 31h ... 40h
- mov [@@status], ax
- fild [@@status]
- sub bx, ax
- mov cl, 4
- fxch st(1)
- shr bx, cl
- mov ax, bx
- fscale
- add bx, (TYPE QWORD) / 2 ; sizes are in words
- mov [(BIGDATA di).len], bx
- lea si, [(BIGDATA di).lsw] ; fill in 0's
- fstp st(1) ; drop the exponent
- @@padloop:
- or ax, ax
- jz @@putmsw
- mov [WORD si], 0
- inc si
- inc si
- dec ax
- jmp @@padloop
- @@putmsw:
- fistp [QWORD si]
- @@done:
- ret
- ENDP flotobig
-
- ;************************************************************************
- ;* Move bytes from buffer to allocated Scheme block *
- ;* Calling sequence: toblock(reg,offs,buf,q) *
- ;* Where reg: Scheme register pointing to block *
- ;* offs: Offset into block to begin transfer *
- ;* buf: Buffer pointer *
- ;* len: Number of bytes to move *
- ;************************************************************************
- PROC C toblock USES si di, @@reg:WORD, @@offset:WORD, @@buf:WORD, @@len:WORD
- mov bx, [@@reg] ; Get register address
- mov di, [(REG bx).disp]
- mov bx, [(REG bx).page]
- ldpage es, bx
- add di, [@@offset]
- mov si, [@@buf]
- mov cx, [@@len]
- cld
- rep movsb
- ret
- ENDP toblock
-
- ;************************************************************************
- ;* Give characters from a C string *
- ;* Calling sequence: gvchars(str,len) *
- ;* Where str: C string address *
- ;* len: Number of characters to give *
- ;************************************************************************
- PROC C gvchars USES si di, @@string:WORD, @@len:WORD
- mov si, [@@string]
- mov cx, [@@len]
- jcxz @@given
- cld
- @@loop:
- push cx
- lodsb
- call givechar C, ax
- pop cx
- loop @@loop
- @@given:
- ret
- ENDP gvchars
-
- ;************************************************************************
- ;* Move characters from block (symbol or string) to print buffer *
- ;* Calling sequence: blk2pbuf(pg,ds,buf,len,ch,display) *
- ;* Where pg: logical page of the block *
- ;* ds: block displacement *
- ;* buf: address of print buffer *
- ;* len: number of chars in the block *
- ;* ch: character to escape (| for syms, " for strs) *
- ;* display: whether to use escape characters *
- ;* Returns the number 2n+s, where n is the number of characters in the *
- ;* print buffer, and s=1 if strange chars were encountered, 0 otherwise.*
- ;************************************************************************
- PROC C blk2pbuf USES ds si di, @@page:WORD, @@disp:WORD, @@buf:WORD, @@len:WORD, @@char:WORD, @@display:WORD
- push ds ; Assume es = ds
- pop es
- mov bx, [@@page]
- shl bx, 1 ; Put segment of block in ds
- ldpage ds, bx
- mov si, [@@disp]
- mov di, [@@buf]
- mov cx, [@@len]
- mov bl, [BYTE @@char]
- mov bh, [BYTE @@display]
- and bh, 7fh ; Save bit in bh for strangeness
- mov dx, di ; Save start address of print buffer in dx
- jcxz @@strange ; If len=0, mark strangeness
- cmp bl, '"' ; are we looking at a string?
- jne @@loop
- @@strange:
- or bh, 80h ; Otherwise, mark as strange
- jcxz @@done ; If len=0, forget everything else
- @@loop:
- lodsb ; Fetch char from block
- test bh, 7fh ; Are we displaying escape chars?
- jz @@storeit
- cmp al, bl ; Does the char need escaping?
- je @@escapeit
- cmp al, '\'
- jne @@storeit
- @@escapeit:
- mov ah, al
- mov al, '\' ; store escape character
- stosb
- mov al, ah ; Restore char
- @@storeit:
- stosb
- test bh, 80h ; Do we already know that atom's strange?
- jnz @@continue
- push bx
- lea bx, [es:hicases]
- mov ah, al
- xlat [es:hicases] ; Fetch upper-case equivalent
- pop bx
- cmp ah, al
- jne @@markstrange
- DATASEG
- @@strangechars DB " ,'"
- DB ';":()`'
- DB 13, 12, 11, 10, 9
- STRANGECOUNT = $-@@strangechars
- CODESEG
- @@strangeloop:
- push cx di
- lea di, [es:@@strangechars]
- mov cx, STRANGECOUNT
- repne scasb
- pop di cx
- jne @@continue
- @@markstrange:
- or bh, 80h ; Mark strange bit
- @@continue:
- loop @@loop
- @@done:
- mov [BYTE es:di], 0 ; Put null at end of string
- mov ax, di ; Return 2*(# of chars in string)+strangeness
- sub ax, dx
- shl bh, 1 ; get strangeness in carry
- rcl ax, 1
- ret
- ENDP blk2pbuf
-
- ;************************************************************************
- ;* Load bignum block with long integer *
- ;* Calling sequence: putlong(reg,longi) *
- ;* Where reg: register pointing to a bignum block *
- ;* longi: 32-bit integer to store *
- ;************************************************************************
- PROC C putlong uses es di, @@reg:WORD, @@long:DWORD
- mov di, [@@reg]
- mov bx, [(REG di).page]
- ldpage es, bx
- mov di, [(REG di).disp]
- add di, OFFSET (TYPE BIGDEF).data.sign
- mov bx, [WORD LOW @@long]
- mov cx, [WORD HIGH @@long]
- xor al, al ; Sign byte - default positive
- or cx, cx
- jns @@positive
- inc al ; Otherwise, set sign negative
- not cx ; negate longint
- neg bx
- sbb cx, -1
- @@positive:
- cld
- stosb ; Store sign byte
- mov ax, bx ; Store least significant word
- stosw
- jcxz @@notsolong
- mov ax, cx
- stosw
- @@notsolong:
- ret
- ENDP putlong
-
- ;************************************************************************
- ;* Move string bytes from one part of PCS memory to another *
- ;* Calling sequence: msubstr(to_reg, from_reg, start, end) *
- ;* Where to_reg:register pointing to destination string *
- ;* from_reg:register pointing to source string *
- ;* start: offset at which to start copying *
- ;* end: byte after the last to be copied *
- ;************************************************************************
- PROC C msubstr USES ds si di, @@toreg:WORD, @@fromreg:WORD, @@start:WORD, @@end:WORD
- mov di, [@@toreg]
- mov si, [@@fromreg]
- mov ax, [@@start]
- mov cx, [@@end]
- mov bx, [(REG di).page]
- mov di, [(REG di).disp]
- ldpage es, bx
- add di, OFFSET (TYPE STRDEF).buffer
- mov bx, [(REG si).page]
- mov si, [(REG si).disp]
- ldpage ds, bx
- add si, OFFSET (TYPE STRDEF).buffer
- add si, ax ; Point ds:si to start of substring
- sub cx, ax ; Set number of bytes to move
- cld
- rep movsb
- ret
- ENDP msubstr
-
- ;************************************************************************
- ;* Compare two Scheme bignums or strings for equal?-ness *
- ;* Calling sequence: mcmpstr(rega,regb) *
- ;* Where rega,regb: registers pointing to objects to be compared *
- ;* Returns 1 if the objects are equal?, 0 otherwise *
- ;************************************************************************
- PROC C mcmpstr USES ds si di, @@reg1:WORD, @@reg2:WORD
- mov si, [@@reg1]
- mov di, [@@reg2]
- mov bx, [(REG di).page]
- mov di, [(REG di).disp]
- ldpage es, bx
- mov bx, [(REG si).page]
- mov si, [(REG si).disp]
- ldpage ds, bx
- sstrlen cx, <si>, OVERHEAD
- xor ax, ax ; Default equality to false
- cld
- repe cmpsb
- jne @@false
- inc ax ; return true
- @@false:
- ret
- ENDP mcmpstr
-
- ;************************************************************************
- ;* Load a register with a pointer from Scheme memory *
- ;* Calling sequence: ldreg(reg,pg,ds) *
- ;* Where reg: register to be loaded *
- ;* pg,ds: page and displacement of Scheme pointer *
- ;************************************************************************
- PROC C ldreg USES ds si di, @@reg:WORD, @@page:WORD, @@disp:WORD
- push ds ; Assume es = ds
- pop es
- mov di, [@@reg]
- mov bx, [@@page]
- mov si, [@@disp]
- shl bx, 1 ; Point ds:si to Scheme pointer
- ldpage ds, bx
- cld
- lodsb ; Load pointer's page field
- xor ah, ah
- mov [(REG es:di).page], ax
- lodsw ; Load displacement field
- mov [(REG es:di).disp], ax
- ret
- ENDP ldreg
-
- ;************************************************************************
- ;* Set the cdr field of a list cell *
- ;* Calling sequence: asetcdr(creg, preg) *
- ;* Where creg: register pointing to cell *
- ;* preg: register holding new pointer *
- ;************************************************************************
- PROC C asetcdr USES si di, @@list:WORD, @@cdr:WORD
- mov di, [@@list]
- mov bx, [(REG di).page]
- mov di, [(REG di).disp]
- ldpage es, bx
- add di, OFFSET (TYPE LISTDEF).cdr
- mov si, [@@cdr]
- cld
- mov ax, [(REG si).page]
- stosb
- mov ax, [(REG si).disp]
- stosw
- ret
- ENDP asetcdr
-
- ;************************************************************************
- ;* Copy bytes from one C location to another *
- ;* Calling sequence: str2str(dest_adr, src_adr, n) *
- ;* Where dest_adr:destination address *
- ;* src_adr:source address *
- ;* n: number of bytes to copy *
- ;************************************************************************
- PROC C str2str USES si di, @@dest:WORD, @@source:WORD, @@len:WORD
- push ds ; Assume es = ds
- pop es
- mov di, [@@dest]
- mov si, [@@source]
- mov cx, [@@len]
- cld
- rep movsb
- ret
- ENDP str2str
-
- ;************************************************************************
- ;* Adjust window region variables for presence of a border *
- ;* Calling sequence: adj4bord(&ull, &nl, &ulc, &nc) *
- ;* Where ull: Upper-left-line variable *
- ;* nl: Number-of-lines variable *
- ;* ulc: Upper-left-column variable *
- ;* nc: Number-of-columns variable *
- ;************************************************************************
- PROC C adj4bord USES si di, @@ull:WORD, @@nl:WORD, @@ulc:WORD, @@nc:WORD
- call get_max_rows C ; Expand HEIGHT of window region
- mov si, [@@ull]
- mov di, [@@nl]
- @@backward:
- mov bx, ax
- mov ax, [si] ; Get value of upper-left parm
- or ax, ax ; If minimum, don't expand
- jz @@forward
- dec [WORD si] ; Else, expand backward
- inc [WORD di]
- dec ax ; Adjust ax to match upper-left parm
- @@forward:
- add ax, [di] ; Find opposite edge
- cmp ax, bx ; If edge too far, don't expand
- jae @@nextsides
- inc [WORD di] ; Else, expand forward
- @@nextsides:
- call get_max_cols C
- dec ax
- cmp bx, ax ; Finished ?
- je @@return
- mov si, [@@ulc] ; Else, expand WIDTH of window region
- mov di, [@@nc]
- jmp @@backward
- @@return:
- ret
- ENDP adj4bord
-
- END